#define _CRT_SECURE_NO_WARNINGS 1

	


			《 Linux_12_gdb 》




——————————————————————————————————————————————————————————————————————————————


——————————————————————————————————————————————————————————————————————————————


        《 Linux调试器 - gdb 》


gdb使用：
1.背景:
	·程序的发布方式有两种，debug模式和release模式
	·Linux gcc / g++ 出来的二进制程序，默认是release模式
	·要使用gdb调试，必须在源代码生成二进制程序的时候, 加上 - g 选项
		
2.开始使用:
gdb binFile退出 : ctrl + d或quit调试命令 :
	list / l 行号        : 显示binFile源代码，接着上次的位置往下列，每次列10行。
	list / l 函数名      : 列出某个函数的源代码。
	r或run               : 运行程序。
	n或next              : 单条执行。
	s或step              : 进入函数调用
	break(b)行号         : 在某一行设置断点
	break函数名          : 在某个函数开头设置断点
	info break           : 查看断点信息。
  finish               : 执行到当前函数返回，然后挺下来等待命令
  print(p)             : 打印表达式的值，通过表达式可以修改变量的值或者调用函数
  p变量                : 打印变量值。
  set var              : 修改变量的值 (比如直接让变量跑到指定位置 set var (变量名)i=100)
  continue(或c)        : 从当前位置开始连续而非单步执行程序
  run(或r)             : 从开始连续而非单步执行程序
  delete breakpoints   : 删除所有断点
  delete breakpoints n : 删除序号为n的断点
  disable breakpoints  : 禁用断点
  enable breakpoints   : 启用断点
  info(或i) breakpoints: 查看当前设置了哪些断点
  display变量名        : 跟踪查看一个变量，每次停下来都显示它的值
  undisplay            : 取消对先前设置的那些变量的跟踪
  until X行号          : 跳至X行
  breaktrace(或bt)     : 查看各级函数调用及参数 (比如查看调用的压栈情况)
  info(i) locals       : 查看当前栈帧局部变量的值
  quit                 : 退出gdb


——————————————————————————————————————————————————————————————————————————————

 gdb myprocess-debug  进入 gdb 工作模式：
 GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7 // 版本
 Reading symbols from / home / a / Desktop / a / aa / myprocess - debug...done.	// debug 读取成功
 (gdb)

 (gdb) quit	// 退出 gdb
 (gdb) q		// quit 的简称 q 也可以退出

		< gdb 本身也是一个进程 >
[a@192 aa]$ ps ajx | grep gdb
2483   2765   2764   2483 pts / 0      2764 R + 1000   0:00 grep --color = auto gdb

——————————————————————————————————————————————————————————————————————————————

(gdb)list			//查看文件对应内容 ：
7		for (i = 0; i <= end; i++)
8		{
9			sum += i;
10		}
11		return sum;
12	}
13
14	int main()
15	{
16		printf("run begin...\n");

——————————————————————————————————————————————————————————————————————————————

	< 从头开始查看 >
 (gdb) l(list的简写) 0(行号) 每次默认显示10行

 (gdb) l 0
1	#include <stdio.h>
2
3	int AddToTarget(int start, int end)
4	{
5		int i = start;
6		int sum = 0;
7		for (i = 0; i <= end; i++)
8		{
9			sum += i;
10		}

 (gdb)l myprocess.c:0		//指定文件 myprocess.c 从 0 开始查。
 (gdb) l myprocess.c:main //指定文件中查找: 行号/函数 ，都是可以查找的。 
 查找每次默认显示10行 显示位置为查找位置的上下5行(并不是以查找位置为开头进行显示的)

  gdb 默认记录，上一条指令，直接回车 执行上一条指令，直到超出范围。
(gdb)
Line number 26 out of range; myprocess.c has 25 lines.	// 当前代码只有25 行，26行超出范围了。


——————————————————————————————————————————————————————————————————————————————

		< (gdb) r  简称 >
(gdb) run		//程序跑起来
Starting program : / home / a / Desktop / a / aa / myprocess - debug
run begin...
result : 5050
run end...
[Inferior 1 (process 3038) exited normally]	//程序没有错误
(gdb)

——————————————————————————————————————————————————————————————————————————————

		< 打断点 (gdb) break >
(gdb)brake // 简写(gdb) b
(gdb)b myprocess.c:main	// 1.指定文件的： 函数位置打断点 
Breakpoint 1 at 0x4005bc : file myprocess.c, line 16.
(gdb)b myprocess.c : 20	// 2.指定文件的： 行号位置打断点 
Breakpoint 2 at 0x4005df : file myprocess.c, line 20.
(gdb)b 22					// 3.当前文件的： 行号位置打断点 
Breakpoint 3 at 0x4005f3 : file myprocess.c, line 22.
(gdb)


		< 查看打断点位置 info >
(gdb) info b
(gdb) i b		//简写
 断点只能一个一个打，不可以连续打断点。
 断点是递增的，即使你删除了该断点，再次打断点时，也不会再用该断点号数。

(gdb)i b
Num     Type           Disp Enb(断点开启Y/N) Address            What
1   breakpoint(断点1)  keep  y     0x00000000004005bc in main at myprocess.c : 16
2   breakpoint(断点2)  keep  y     0x00000000004005df in main at myprocess.c : 20
3   breakpoint(断点3)  keep  y     0x00000000004005f3 in main at myprocess.c : 22
(gdb)

		< 删除断点 delete > 
   < delete breakpoints: 删除所有断点 >
 删除断点只能，删除几号断点的形式， 不能（gdb） d myprocess.c:20 以这种形式删！	// err
(gdb)d 2		// 删除 2 号断点
(gdb)i b		// 查看打断点位置
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004005bc in main at myprocess.c:16
3       breakpoint     keep y   0x00000000004005f3 in main at myprocess.c : 22
(gdb)


		< 关闭断点 disable >
(gdb) disable 7	// 关闭7号断点,Enb↓被改为 n  
 7       breakpoint     keep   n(Y/N)   0x00000000004005df in main at myprocess.c:20

 (gdb)enable 7	// 开启7号断点,Enb↓被改为 y
 7       breakpoint     keep   y(Y/N)   0x00000000004005df in main at myprocess.c:20


		< 从一个断点到另一个断点 continue >
(gdb) run 进入调试模式
(gdb) continue	// (gdb)c			//简写
Continuing.
run begin...		// 运行结果

Breakpoint 2, main() at myprocess.c:18
18		int result = 0;
(gdb)c
Continuing.
result:5050

Breakpoint 3, main() at myprocess.c : 22
22		printf("run end...\n");
(gdb)


——————————————————————————————————————————————————————————————————————————————

		< 逐过程/逐语句 >
 
(gdb)next	// 逐过程
19		result = AddToTarget(1, 100);
(gdb)n	// 简写 n  == VS: F10
20		printf("result:%d\n", result);
(gdb)		//（gdb）默认记住上一次执行指令，直接回车。
result:5050
22		printf("run end...\n");
(gdb)

(gdb)step	// 逐语句( step: 步;步骤 )
(gdb)s		// 简写 s  == VS: F11
AddToTarget(start = 1, end = 100) at myprocess.c:5
5		int i = start;
(gdb)

		< 逐函数 finish >
(gdb) strp 进入函数后： 
(gdb)finish
Run till exit from #0  AddToTarget(start = 1, end = 100) at myprocess.c:6
0x00000000004005dc in main() at myprocess.c : 19
19		result = AddToTarget(1, 100);
Value returned is $1 = 5050
(gdb)

		< 跳转到指定行 until >
(gdb)next/step //进入函数体内部，逐步运行时
 想要快速跑完循环体 到指定 11行：
(gdb)until 11
AddToTarget(start = 1, end = 100) at myprocess.c:11
11		return sum;
(gdb)


——————————————————————————————————————————————————————————————————————————————

		< 调试查看变量 >
(gdb)print i

7		for (i = 0; i <= end; i++)
(gdb)p i	// 简写
$1 = 1
(gdb)p sum
$2 = 0
(gdb)p & i
$3 = (int*)0x7fffffffdf2c
(gdb)

		< 调试查看常显示 display >
(gdb)display i 
1: i = 0
(gdb)display sum
2 : sum = 0
(gdb)display end
3 : end = 100
(gdb)display & i
4 : &i = (int*)0x7fffffffdf2c
(gdb)n
 ...
7		for (i = 0; i <= end; i++)
4: &i = (int*)0x7fffffffdf2c
3 : end = 100
2 : sum = 10
1 : i = 4
(gdb)

		< 取消常显示 undisplay >
(gdb) undisplay + 编号

(gdb)undisplay 3
(gdb)undisplay 2
(gdb)n
7		for (i = 0; i <= end; i++)
4: &i = (int*)0x7fffffffdf2c
1 : i = 5
(gdb)


		< 查看函数体内部临时变量 info local >
 进入函数内部后：
(gdb)info local
(gdb)i local	// 只能简写 info
i = 2
sum = 1


——————————————————————————————————————————————————————————————————————————————


		< 修改变量的值 set var > 
 //循环时：
(gdb)
9			sum += i;
1: i = 5			
想直接把变量设置成某个值，查看对当前程序的执行影响
// 可以使用 ：set var 变量=要修改的值 
(gdb)set var i = 100
(gdb)print i	//查看一下要修改的值是否修改成功
$1 = 100
(gdb)n			//继续用修改后的值运行程序
7		for (i = 0; i <= end; i++)
1: i = 100
(gdb)
11		return sum;
1: i = 101


——————————————————————————————————————————————————————————————————————————————

  < breaktrace(或bt): 查看各级函数调用及参数 >
 函数压栈的效果：
(gdb)bt
#0  AddToTarget(start = 1, end = 100) at myprocess.c:12
#1  0x00000000004005dc in main() at myprocess.c:19
(gdb)

——————————————————————————————————————————————————————————————————————————————



